#pragma once
#include "../protocol/protocol.h"
#include <cstdint>
#include <iostream>
// #include "protocol.h" // 假设这个文件定义了 MessageHeader 和 OperationType

// --- 平台相关的头文件和类型定义 ---
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
using socket_t = SOCKET; // 为套接字类型定义一个别名
const int SOCKET_ERROR_VAL = SOCKET_ERROR;
#elif defined(__linux__)
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h> // for close()
#include <cerrno>   // for errno
#include <cstring>  // for strerror
using socket_t = int; // 在 Linux 上，套接字是 int
const socket_t INVALID_SOCKET_VAL = -1;
const int SOCKET_ERROR_VAL = -1;
#endif

/**
 * @brief 健壮地从套接字接收指定大小的数据。
 * @param sock 套接字描述符。
 * @param buffer 用于存储数据的缓冲区。
 * @param size 要接收的字节数。
 * @return true 如果成功接收所有数据，否则返回 false。
 */
inline bool recv_all(socket_t sock, void *buffer, int size)
{
    char *p = static_cast<char *>(buffer);
    int bytes_left = size;

    while (bytes_left > 0)
    {
        // recv 的参数在两个平台上是兼容的
        int bytes_received = recv(sock, p, bytes_left, 0);

        if (bytes_received == 0)
        {
            // 对端关闭了连接
            std::cerr << "Connection closed by peer." << std::endl;
            return false;
        }

        if (bytes_received == SOCKET_ERROR_VAL)
        {
            // 发生错误，根据平台获取错误信息
#ifdef _WIN32
            std::cerr << "recv failed with error: " << WSAGetLastError() << std::endl;
#elif defined(__linux__)
            // strerror(errno) 会将错误码转换为可读的字符串
            std::cerr << "recv failed with error: " << errno << " (" << strerror(errno) << ")" << std::endl;
#endif
            return false;
        }

        p += bytes_received;
        bytes_left -= bytes_received;
    }
    return true;
}
inline bool recv_all(socket_t sock, void *buffer, int size, std::string client_ip, int client_port)
{
    char *p = (char *)buffer;
    int bytes_left = size;
    while (bytes_left > 0)
    {
        int bytes_received = recv(sock, p, bytes_left, 0);
        if (bytes_received <= 0)
        {
            if (bytes_received == 0) // 2. 客户端正常关闭了连接
            {
                std::cout << "Client " << client_ip << ":" << client_port << " disconnected gracefully." << std::endl;
                break; // 跳出循环
            }
            else // 3. recv返回 SOCKET_ERROR，需要检查具体错误码
            {   
                #ifdef _WIN32
                // Windows 平台
                int err = WSAGetLastError();
                // 关键：检查是否为非阻塞错误
                if (err == WSAEWOULDBLOCK)
                {
                    // 这不是一个真正的错误，只是表示暂时没有数据可读
                    // 短暂休眠一下，避免CPU空转，然后继续循环等待数据
                    Sleep(10); // 休眠10毫秒
                    continue;  // 继续下一次循环
                }
                #elif defined(__linux__)
                // Linux 平台
                int err = errno;
                // 关键：检查是否为非阻塞错误
                if (err == EWOULDBLOCK || err == EAGAIN)
                {
                    // 这不是一个真正的错误，只是表示暂时没有数据可读
                    // 短暂休眠一下，避免CPU空转，然后继续循环等待数据
                    usleep(10000); // 休眠10毫秒
                    continue;      // 继续下一次循环
                }
                #endif
                else
                {
                    // 其他错误，是真正的连接问题
                    std::cerr << "Error reading from socket " << client_ip << ":" << client_port << ". Error code: " << err << std::endl;
                    break; // 发生致命错误，跳出循环
                }
            }
        }
        p += bytes_received;
        bytes_left -= bytes_received;
    }
    return true;
}

/**
 * @brief 发送一个带有 "消息头+消息体" 格式的数据包。
 * @param sock 套接字描述符。
 * @param type 消息类型。
 * @param body 指向消息体的指针。
 * @param body_size 消息体的大小（字节）。
 * @return true 如果成功发送，否则返回 false。
 */
inline bool send_packet(socket_t sock, OperationType type, const void *body, uint32_t body_size)
{
    // 1. 创建并填充消息头
    MessageHeader header;
    header.type = type;
    header.length = htonl(body_size); // htonl 在两个平台上都可用 (winsock2.h / arpa/inet.h)

    // 2. 发送消息头
    if (send(sock, (const char *)&header, sizeof(MessageHeader), 0) == SOCKET_ERROR_VAL)
    {
#ifdef _WIN32
        std::cerr << "send header failed with error: " << WSAGetLastError() << std::endl;
#elif defined(__linux__)
        std::cerr << "send header failed with error: " << errno << " (" << strerror(errno) << ")" << std::endl;
#endif
        return false;
    }

    // 3. 发送消息体 (如果消息体存在)
    if (body_size > 0)
    {
        if (send(sock, (const char *)body, body_size, 0) == SOCKET_ERROR_VAL)
        {
#ifdef _WIN32
            std::cerr << "send body failed with error: " << WSAGetLastError() << std::endl;
#elif defined(__linux__)
            std::cerr << "send body failed with error: " << errno << " (" << strerror(errno) << ")" << std::endl;
#endif
            return false;
        }
    }
    return true;
}

inline void close_socket(socket_t sock)
{
#ifdef _WIN32
    closesocket(sock);
#elif defined(__linux__)
    close(sock);
#endif
}